/*=============================================================================
// File Name:   drv_spi.c
// Author:      Wood Wang
// Date:        2020/03/14
// Version:     v1.0

=============================================================================*/
/* Includes -----------------------------------------------------------------*/
#include "drv_gpio.h"
#include "drv_spi.h"


void drv_spi_gpio_init(void)
{
    CLOCK_EnableClock(kCLOCK_Iocon);
    CLOCK_EnableClock(kCLOCK_Gpio0);
    CLOCK_EnableClock(kCLOCK_Gpio1);
    
    CLOCK_EnableClock(kCLOCK_Spi0);
    CLOCK_EnableClock(kCLOCK_Spi1);
    CLOCK_Select(kSPI0_Clk_From_MainClk);
    CLOCK_Select(kSPI1_Clk_From_MainClk);
    RESET_PeripheralReset(kSPI0_RST_N_SHIFT_RSTn);
    RESET_PeripheralReset(kSPI1_RST_N_SHIFT_RSTn);

    gpio_pin_config_t SPILCD_IN_config = {
        .pinDirection = kGPIO_DigitalInput,
        .outputLogic = 1U,
    };
    gpio_pin_config_t SPILCD_IOH_config = {
        .pinDirection = kGPIO_DigitalOutput,
        .outputLogic = 1U,
    };
    gpio_pin_config_t SPILCD_IOL_config = {
        .pinDirection = kGPIO_DigitalOutput,
        .outputLogic = 0U,
    };
    /* Initialize GPIO functionality on pin */
    GPIO_PinInit(GPIO, 0,11, &SPILCD_IOL_config);//LCD_BLK
    GPIO_PinInit(GPIO, 0,10, &SPILCD_IOH_config);//LCD_DC
    GPIO_PinInit(GPIO, 0,27, &SPILCD_IOH_config);//LCD_RST
    GPIO_PinInit(GPIO, 1, 1, &SPILCD_IOH_config);//LCD_CS
    GPIO_PinInit(GPIO, 0,16, &SPILCD_IOH_config);//LCD_CLK
    GPIO_PinInit(GPIO, 1, 2, &SPILCD_IOH_config);//LCD_MOSI
    
    
    GPIO_PinInit(GPIO, 1,8, &SPILCD_IOH_config); //FLASH_CS
    GPIO_PinInit(GPIO, 1,9, &SPILCD_IN_config); //FLASH_MISO
    GPIO_PinInit(GPIO, 0,12, &SPILCD_IOH_config);//FLASH_CLK
    GPIO_PinInit(GPIO, 0,13, &SPILCD_IOH_config);//FLASH_MOSI
    
    const uint32_t spilcd_ioc = (/* Selects pull-up function */
                              IOCON_PIO_MODE_PULLUP |
                              /* Enable hysteresis */
                              IOCON_PIO_HYS_EN |
                              /* Input not invert */
                              IOCON_PIO_INV_DI |
                              0x100| //GPIO not i2c mode
                              /* Disables Open-drain function */
                              IOCON_PIO_OD_DI |
                              /* Bypass input filter */
                              IOCON_PIO_SMODE_BYPASS |
                              /* IOCONCLKDIV0 */
                              IOCON_PIO_CLKDIV0);
    IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO0_11,  spilcd_ioc);   //LCD_BLK
    IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO0_10,  spilcd_ioc);   //LCD_DC
    IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO0_27,  spilcd_ioc);   //LCD_RST
    IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO1_1 ,  spilcd_ioc);   //LCD_CS
    
    /* Enables clock for switch matrix.: enable */
    const uint32_t SPI_LCD_CLK = (/* Selects pull-up function */
                                    IOCON_PIO_MODE_PULLUP |
                                    /* Enable hysteresis */
                                    IOCON_PIO_HYS_EN |
                                    /* Input not invert */
                                    IOCON_PIO_INV_DI |
                                    /* Disables Open-drain function */
                                    IOCON_PIO_OD_DI |
                                    /* Bypass input filter */
                                    IOCON_PIO_SMODE_BYPASS |
                                    /* IOCONCLKDIV0 */
                                    IOCON_PIO_CLKDIV0);
    IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO0_16, SPI_LCD_CLK);

    const uint32_t SPI_LCD_MOSI = (/* Selects pull-up function */
                                    IOCON_PIO_MODE_PULLUP |
                                    /* Enable hysteresis */
                                    IOCON_PIO_HYS_EN |
                                    /* Input not invert */
                                    IOCON_PIO_INV_DI |
                                    /* Disables Open-drain function */
                                    IOCON_PIO_OD_DI |
                                    /* Bypass input filter */
                                    IOCON_PIO_SMODE_BYPASS |
                                    /* IOCONCLKDIV0 */
                                    IOCON_PIO_CLKDIV0);
    IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO1_2, SPI_LCD_MOSI);
    
    const uint32_t SPI_MISO = (/* Selects pull-up function */
                                    0 |
                                    /* Enable hysteresis */
                                    IOCON_PIO_HYS_EN |
                                    /* Input not invert */
                                    IOCON_PIO_INV_DI |
                                    /* Disables Open-drain function */
                                    IOCON_PIO_OD_DI |
                                    /* Bypass input filter */
                                    IOCON_PIO_SMODE_BYPASS |
                                    /* IOCONCLKDIV0 */
                                    IOCON_PIO_CLKDIV0);
    IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO1_9, SPI_MISO);   //f_miso

    IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO1_8,   spilcd_ioc);   //f_cs
    IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO0_12,  spilcd_ioc);   //f_clk
    IOCON_PinMuxSet(IOCON, IOCON_INDEX_PIO0_13,  spilcd_ioc);   //f_mosi
    
    CLOCK_EnableClock(kCLOCK_Swm);
    SWM_SetMovablePinSelect(SWM0, kSWM_SPI0_SCK,   kSWM_PortPin_P0_16); //lcd_clk
    SWM_SetMovablePinSelect(SWM0, kSWM_SPI0_MOSI,  kSWM_PortPin_P1_2);  //lcd_mosi
    
    SWM_SetMovablePinSelect(SWM0, kSWM_SPI1_MISO,  kSWM_PortPin_P1_9);  //F_MISO
    SWM_SetMovablePinSelect(SWM0, kSWM_SPI1_MOSI,  kSWM_PortPin_P0_13); //F_MOSI
    SWM_SetMovablePinSelect(SWM0, kSWM_SPI1_SCK ,  kSWM_PortPin_P0_12); //F_CLK
    /* Disable clock for switch matrix. */
    CLOCK_DisableClock(kCLOCK_Swm);
    
    spi_master_config_t userConfig = {0};
    uint32_t srcFreq               = 0U;
    /* Note: The slave board using interrupt way, slave will spend more time to write data
     *       to TX register, to prevent TX data missing in slave, we will add some delay between
     *       frames and capture data at the second edge, this operation will make the slave
     *       has more time to prapare the data.
     */
    
    SPI_MasterGetDefaultConfig(&userConfig);
    userConfig.baudRate_Bps           = 30000000;
    userConfig.sselNumber             = kSPI_Ssel0Assert;
    userConfig.clockPolarity          = kSPI_ClockPolarityActiveHigh;
    userConfig.clockPhase             = kSPI_ClockPhaseFirstEdge;
    userConfig.direction              = kSPI_MsbFirst;
    userConfig.delayConfig.preDelay   = 0x0U;
    userConfig.delayConfig.postDelay  = 0x0U;
    userConfig.delayConfig.frameDelay = 0x0U;
    userConfig.delayConfig.transferDelay = 0x0U;
    srcFreq                           = CLOCK_GetFreq(kCLOCK_MainClk);
    SPI_MasterInit(SPI0, &userConfig, srcFreq);
    
    SPI_MasterInit(SPI1, &userConfig, srcFreq);

}




SPI_Type * spi_table[2]=
{
    SPI0,
    SPI1,
};

void spi_pre_h(void)
{

}

void spi_pre_l(void)
{

}

void spi_writebyte(uint8_t index,uint8_t TxData)
{
    spi_table[index]->TXDATCTL = TxData | 0X077E0000;
    while ((spi_table[index]->STAT & SPI_STAT_TXRDY_MASK) == 0U){;}
}

uint8_t spi_readbyte(uint8_t index)
{
    uint8_t re;
    spi_table[index]->TXDATCTL = 0xff | 0X073E0000;
    while ((spi_table[index]->STAT & SPI_STAT_RXRDY_MASK) == 0U){;}
    re = spi_table[index]->RXDAT & 0XFF;
    return re;
}


uint8_t spi_writebuff(uint8_t index,uint8_t *buff,uint32_t len)
{
    spi_transfer_t xfer = {0};
    /*Start Transfer*/
    xfer.txData      = buff;
    xfer.rxData      = NULL;
    xfer.dataSize    = len;
    xfer.configFlags = kSPI_EndOfTransfer | kSPI_EndOfFrame | kSPI_ReceiveIgnore;
    /* Transfer data in polling mode. */
    SPI_MasterTransferBlocking(spi_table[index], &xfer);
    
    return 0;
}

uint8_t spi_readbuff(uint8_t index,uint8_t *buff,uint32_t len)
{
    spi_transfer_t xfer = {0};
    /*Start Transfer*/
    xfer.txData      = buff;
    xfer.rxData      = buff;
    xfer.dataSize    = len;
    xfer.configFlags = kSPI_EndOfTransfer | kSPI_EndOfFrame ;
    /* Transfer data in polling mode. */
    SPI_MasterTransferBlocking(spi_table[index], &xfer);
    return 0;
}

void spi_write_read(uint8_t index,uint8_t * wbuf,uint32_t wl,uint8_t * rbuf,uint32_t rl)
{
    if((wbuf != NULL) && (wl != 0))
    {
        spi_writebuff(index,wbuf,wl);
    }

    if((rbuf != NULL) && (rl != 0))
    {
        spi_readbuff(index,rbuf,rl);
    }
}


